package com.authine.cloudpivot.ext.kingdee.work;

import com.alibaba.fastjson.JSON;
import com.authine.cloudpivot.ext.constants.KingDeeConstant;
import com.authine.cloudpivot.ext.constants.ModelConst;
import com.authine.cloudpivot.ext.constants.PlatformConst;
import com.authine.cloudpivot.ext.dto.kingDee.Certificate;
import com.authine.cloudpivot.ext.dto.kingDee.CredentialDeleteEntity;
import com.authine.cloudpivot.ext.dto.kingDee.KingDeeBusiness;
import com.authine.cloudpivot.ext.dto.kingDee.request.*;
import com.authine.cloudpivot.ext.dto.kingDee.result.ErrorData;
import com.authine.cloudpivot.ext.dto.kingDee.result.ResponseResult;
import com.authine.cloudpivot.ext.dto.voucher.KingDeeBasicStats;
import com.authine.cloudpivot.ext.dto.voucher.RecordVoucher;
import com.authine.cloudpivot.ext.dto.voucher.Voucher;
import com.authine.cloudpivot.ext.enums.kingdee.BusinessType;
import com.authine.cloudpivot.ext.enums.kingdee.FAccountIdEnum;
import com.authine.cloudpivot.ext.enums.kingdee.FormEnum;
import com.authine.cloudpivot.ext.enums.kingdee.OrganizationRiseEnum;
import com.authine.cloudpivot.ext.kingdee.KingDeeExecutor;
import com.authine.cloudpivot.ext.kingdee.VoucherExecutor;
import com.authine.cloudpivot.ext.kingdee.jdbc.KingDeeBasicStatsRepository;
import com.authine.cloudpivot.ext.kingdee.jdbc.RecordVoucherRepository;
import com.authine.cloudpivot.ext.kingdee.jdbc.VoucherRepository;
import com.authine.cloudpivot.ext.utils.kingdee.DateUtils;
import com.authine.cloudpivot.ext.utils.kingdee.KingDeeUtils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author: liwei
 * @DateTime: 2021/7/16
 * @Description: TODO
 */
@Slf4j
public class BaseWork {

    public ObjectMapper objectMapper = new ObjectMapper();
    public KingDeeConstant baseConstant = new KingDeeConstant();
    private String setOfAccount;

    public VoucherRepository voucherRepository = new VoucherRepository();
    public RecordVoucherRepository recordVoucherRepository = new RecordVoucherRepository();
    public KingDeeBasicStatsRepository kingDeeBasicStatsRepository = new KingDeeBasicStatsRepository();


    /**
     * 批量保存 凭证记录
     *
     * @param voucherList
     * @return
     */

    public List<Voucher> saveVoucherList(List<Voucher> voucherList) {

        List<Voucher> beans = new ArrayList();

        for (Voucher voucher : voucherList) {
            Map<String, Object> data = JSON.parseObject(JSON.toJSONString(voucher), HashMap.class);
            voucherRepository.create(data);

            //log.info("批量保存凭证的数据  insert:{}",insert);
            //todo 直接返回map
//            SingleResponse<BO> bo = BoServiceUtils.createBo(ModelConst.T_VOUCHER, Collections.singletonList(data));
//
//            if (bo.getData().getData() != null) {
//                Voucher bean = transferMapToVoucher(bo.getData().getData());
//                beans.add(bean);
//            }
        }
        log.info("批量保存的数据 bo:{}", beans);
        return beans;
    }


    /**
     * 将返回的map集合转换成 voucher对象
     *
     * @param data
     * @return
     */

    public Voucher transferMapToVoucher(Map<String, Object> data) {
        Voucher voucher = new Voucher();
        voucher.setId(data.get("id").toString());
        voucher.setBusiness_id(data.get("business_id").toString());
        voucher.setBusiness_type(BusinessType.valueOf(data.get("business_type").toString()));
        voucher.setRemark(data.get("remark").toString());
        voucher.setSubject_coding(data.get("subject_coding").toString());
        voucher.setDebit_amount(new BigDecimal(data.get("debit_amount").toString()));
        voucher.setCredit_amount(new BigDecimal(data.get("credit_amount").toString()));
        voucher.setAccount_name(data.get("account_name").toString());
        voucher.setVersion(data.get("version").toString());
        voucher.setDel(Boolean.getBoolean(data.get("del").toString()));
        return voucher;
    }


    /**
     * 根据发票抬头 获取对应的金蝶客户表里的编码
     *
     * @param parentCustomerName
     * @return
     */

    public String getKingDeeCode(String parentCustomerName) {

        String codeName = KingDeeUtils.noBrackets(parentCustomerName.trim());
        List<String> names = new ArrayList<>();
        names.add(parentCustomerName);
        names.add(codeName);

        //todo JdbcTemplateUtils
        List<KingDeeBasicStats> list = kingDeeBasicStatsRepository.findByCompanyNames(names);

        if (null == list || list.size() == 0) {
            return KingDeeConstant.KINGDEE_BASIC_STATS_CODE;
        }

        return list.get(0).getKingdee_code();
        //return (String) boList.getData().getData().get(0).get("kingdee_code");
    }

    /**
     * 保存记录到金蝶 & 保存凭证记录数据
     *
     * @param formEnum
     * @param kingDeeEntity
     * @param kingDeeBusiness
     */

    public void doSaveKingDeeAndRecord(FormEnum formEnum, KingDeeEntity kingDeeEntity, KingDeeBusiness kingDeeBusiness) {
        try {
            Certificate certificate = new Certificate(formEnum, objectMapper.writeValueAsString(kingDeeEntity), kingDeeBusiness);
            // todo 第一次凭证记录生成
            String recordVoucherId = saveRecordVoucherFirst(certificate);
            log.info("第一次凭证记录生成");
            // todo 保存后的凭证id 给到 凭证实体数据，方便后面数据的更新维护
            KingDeeBusiness business = certificate.getBusiness();
            business.setId(recordVoucherId);
            // todo 判断当前的组织账套名称，然后调用对应组织的接口
            setOfAccount = getAccountName(certificate.getBusiness().getAccountName());
            // todo 调用金蝶第三方，登录，保存
            KingDeeExecutor kingDeeExecutor = new KingDeeExecutor();
            String invoke = kingDeeExecutor.saveLogic(setOfAccount, baseConstant.KINGDEE_USERNAME, baseConstant.KINGDEE_PASSWORD, Integer.valueOf(baseConstant.KINGDEE_LANGUAGE), baseConstant.KINGDEE_URL, certificate);
            Assert.isTrue(StringUtils.isNotBlank(invoke), "金蝶接口调用异常");
            // 解析调用返回数据
            ResponseResult responseResult = objectMapper.readValue(invoke, ResponseResult.class);
            //todo 获取金蝶返回的凭证id
            String number = getResponseResultNumber(responseResult);
            //todo 返回结果数据解析
            String errorMsg = getResponseResultMessage(responseResult, number);

            //todo 调用金蝶之后，新增凭证记录数据封装
            RecordVoucher voucherEntity = new RecordVoucher(number,
                    certificate.getBusiness().getBusinessId(),
                    certificate.getBusiness().getNumber(),
                    certificate.getBusiness().getBusinessType().name(),
                    responseResult.getResult().getResponseStatus().isSuccess(),
                    certificate.getContent(), invoke, errorMsg);
            if (certificate.getBusiness().getAccountName() != null) {
                voucherEntity.setAccount_name(getPlatformName(certificate.getBusiness().getAccountName()));
            } else {
                //如果账套名为空，默认凭证进“上海固买供应链管理有限公司” 账套
                voucherEntity.setAccount_name(OrganizationRiseEnum.GM.toString());
            }
            //todo 调用金蝶完成之后，最后一次生成凭证记录，包括更新之前的记录
            String id = saveRecordVoucherLast(certificate.getBusiness().getId(), voucherEntity);

            log.info("save certificate log：{}", id);

        } catch (JsonProcessingException e) {
            log.info("转换异常  data:{}", e.getMessage());

        }
    }

    public String getPlatformName(String accountName) {
        if (StringUtils.isBlank(accountName)) {
            return null;
        }
        if (accountName.equals(PlatformConst.PLATFORM_ORGANIZATIONS.get("2"))) {
            return "2";
        }
        return "1";
    }

    /**
     * 请求金蝶之前，保存一条凭证记录
     *
     * @param certificate
     * @return
     */

    public String saveRecordVoucherFirst(Certificate certificate) {
        //todo 保存一次凭证记录数据  RecordVoucher
        RecordVoucher build = RecordVoucher.builder()
                .business_id(certificate.getBusiness().getBusinessId())
                .invoice_no(certificate.getBusiness().getNumber())
                .request(certificate.getContent())
                .is_success(false)
                .business_type(certificate.getBusiness().getBusinessType().name()) //业务类型
                .build();

        log.info("保存一次凭证记录数据 data:{}",build);
        HashMap<String, Object> map = JSON.parseObject(JSON.toJSONString(build), HashMap.class);

        recordVoucherRepository.create(map);

        //todo 使用原生的 jdbc 操作 api

        return (String)map.get("id");
    }

    /**
     * 根据账套名称，获取对应的编号
     *
     * @param accountName
     * @return
     */

    public String getAccountName(String accountName) {

        if (StringUtils.isEmpty(accountName) || accountName.equals(OrganizationRiseEnum.GM.toString())) {
            return baseConstant.KINGDEE_DBID_SH;
        }
        return baseConstant.KINGDEE_DBID_HN;
    }

    /**
     * 解析金蝶的返回参数
     *
     * @param responseResult
     * @param number
     * @return
     */

    public String getResponseResultMessage(ResponseResult responseResult, String number) {
        StringBuilder msg = new StringBuilder();
        if (responseResult.getResult().getResponseStatus().isSuccess()) {
            log.info("access K3 successfully return Voucher number:{}", number);
        } else {
            // 拼接返回多个错误信息
            for (ErrorData r : responseResult.getResult().getResponseStatus().getErrorDataList()) {
                if (r.getMessage() != null) {
                    msg.append(r.getMessage());
                }
            }
            log.warn("access K3 warn return message：{}", msg);
        }
        return msg.length() < 1 ? "" : StringUtils.join(msg, ",");
    }

    /**
     * 获取成功之后 的 kingdee 凭证
     *
     * @param responseResult
     * @return
     */

    public String getResponseResultNumber(ResponseResult responseResult) {
        if (responseResult.getResult().getResponseStatus().getSuccessDataList().size() > 0) {
            return responseResult.getResult().getResponseStatus().getSuccessDataList().get(0).getNumber();
        }
        return "";
    }

    /**
     * 请求金蝶之后，保存请求结果的数据
     *
     * @param id
     * @param voucherEntity
     * @return
     */

    public String saveRecordVoucherLast(String id, RecordVoucher voucherEntity) {
        log.info("请求金蝶后保存 凭证记录数据 开始 id:{}", id);
        // 把发送前存的凭证记录数据改掉
        //todo JdbcTemplateUtils
        recordVoucherRepository.del(id);
        //凭证记录中间表 消费后 把请求k3返回的数据放进去

        log.info("请求金蝶后保存 凭证记录数据 data:{}",voucherEntity);
        HashMap<String, Object> data = JSON.parseObject(JSON.toJSONString(voucherEntity), HashMap.class);
        //重新写入一条新的数据
        recordVoucherRepository.create(data);
        return (String) data.get("id");
    }


    /**
     * 转采部分 删除凭证记录数据 & 删除金蝶相关记录
     *
     * @param id
     * @param businessType
     * @param accountName
     */

    public void deleteRecordAndUpdate(String id, BusinessType businessType, String accountName) {

        //根据参数查询 记录数据
        //todo JdbcTemplateUtils

        List<RecordVoucher> recordVoucherList = recordVoucherRepository.findByBusinessIdAndBusinessType(id,businessType);
        //查询返回数据
        if (CollectionUtils.isEmpty(recordVoucherList)) {
            log.info(" ============== <<<<<没有找到凭证记录数据>>>>> id:{},businessType:{},accountName:{}",id,businessType,accountName);
            return;
        }
        for (RecordVoucher recordVoucher : recordVoucherList) {
            //判断 金蝶凭证是否存在 如果存在就需要去 金蝶那边删除数据
            if (StringUtils.isNotBlank(recordVoucher.getVoucher_id())) {
                KingDeeBusiness business = new KingDeeBusiness();
                business.setAccountName(accountName);
                //todo JdbcTemplateUtils
                recordVoucherRepository.del(recordVoucher.getId());
                log.info("删除");
                CredentialDeleteEntity deleteEntity = CredentialDeleteEntity.delete(Arrays.asList(recordVoucher.getVoucher_id()));

                try {
                    Certificate certificate = new Certificate(FormEnum.VOUCHER, objectMapper.writeValueAsString(deleteEntity), business);
                    String dbId = getAccountName(accountName);
                    //调用金蝶的删除逻辑
                    KingDeeExecutor kingDeeExecutor = new KingDeeExecutor();
                    String invoke = kingDeeExecutor.deleteLogic(dbId, baseConstant.KINGDEE_USERNAME, baseConstant.KINGDEE_PASSWORD, Integer.valueOf(baseConstant.KINGDEE_LANGUAGE), baseConstant.KINGDEE_URL, certificate);
                    Assert.isTrue(StringUtils.isNotBlank(invoke), "金蝶接口调用异常");

                    log.info("取消付款删除凭证  调用金蝶接口 result:{}", invoke);

                } catch (JsonProcessingException jsonProcessingException) {
                    jsonProcessingException.printStackTrace();
                }
            }
        }

        //更新记录表 需要先查出来，然后再更新
        //todo JdbcTemplateUtils
        List<RecordVoucher> list = recordVoucherRepository.findByBusinessId(id);
        //SingleResponse<BOList> finds = BoServiceUtils.findListBySimple(ModelConst.T_RECORD_VOUCHER, "business_id", id);
        for (RecordVoucher recordVoucher : list) {
            recordVoucherRepository.del(recordVoucher.getId());
        }

    }

    /**
     * 封装 KingDeeEntity 对象
     *
     * @param fEntityList
     * @param business
     * @return
     */

    public KingDeeEntity getKingDeeEntity(List<FEntity> fEntityList, KingDeeBusiness business) {

        KingDeeEntity king = new KingDeeEntity();

        ModelEntity model = ModelEntity.addModel();
        model.setFSourceBillKey(new FSourceBillKeyEntity(baseConstant.KINGDEE_SOURCEBILLKEY));
        if (business.getAttachments() != null) {
            model.setFAttachments(business.getAttachments());
        } else {
            List<FAccountIdEntity> collect = fEntityList.stream().map(FEntity::getFAccountId).collect(Collectors.toList());
            boolean paymentType = false;
            for (FAccountIdEntity fAccountIdEntity : collect) {
                if (fAccountIdEntity.getFNumber() == FAccountIdEnum.bank.getFNumber()) {
                    paymentType = true;
                }
            }
            int attach = VoucherExecutor.getAttachments(paymentType, business.getBusinessType());
            model.setFAttachments(attach);
        }
        if (business.getBusinessType().equals(BusinessType.OrderTransfer)) {
            model.setFVouchergroupid(FVoucherGroupIdEntity.addTurn());
        }

        if (business.getTime() == null) {
            model.setFDate(DateUtils.dateToStr(new Date()));
        } else {
            model.setFDate(DateUtils.dateToStr(business.getTime()));
        }

        model.setFEntity(fEntityList);
        king.setModel(Arrays.asList(model));

        return king;
    }


    /**
     * 通过平台税率 获取对应的金蝶税率科目
     * 应交税费-应交增值税--进项税额
     *
     * @param taxRate
     */

    public Integer getIntoTax(BigDecimal taxRate) {

        if (taxRate.compareTo(new BigDecimal("0.16")) == 0) {
            return 9;
        }
        if (taxRate.compareTo(new BigDecimal("0.10")) == 0) {
            return 10;
        }
        if (taxRate.compareTo(new BigDecimal("0.06")) == 0 ) {
            return 11;
        }
        if (taxRate.compareTo(new BigDecimal("0.05")) == 0 ) {
            return 12;
        }
        if (taxRate.compareTo(new BigDecimal("0.03")) == 0 ) {
            return 13;
        }
        if (taxRate.compareTo(new BigDecimal("0.015")) == 0 ) {
            return 14;
        }
        if (taxRate.compareTo(new BigDecimal("0.13")) == 0 ) {
            return 15;
        }
        if (taxRate.compareTo(new BigDecimal("0.09")) == 0 ) {
            return 16;
        }
        if (taxRate.compareTo(new BigDecimal("0.01")) == 0 ) {
            return 34;
        }
        if (taxRate.compareTo(new BigDecimal("0.00")) == 0 ) {
            return 0;
        }
        return null;
    }


}
